<!DOCTYPE html>
<html lang="en">

<head>
	<title>3d</title>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=10, maximum-scale=10">
	<style>
		html,
		body {
			height: 100%;
			width: 100%;
			margin: 0;
			overflow: hidden;
		}

		.circleBox {
			width: 30px;
			height: 30px;
			/* display: block; */
			display: none;
			/* width: 200px;
			height: 500px; */
			position: absolute;
			/* top: 20%; */
		}

		.circle1,
		.circle2,
		.circle3,
		.circle4,
		.circle5 {
			width: 30px;
			height: 30px;
			border-radius: 50%;
			position: absolute;
			/* top: 20%; */
		}

		#body1 {
			top: 23%;
			left: 45%;
		}

		#body2 {
			top: 33%;
			left: 43%;
		}

		#body3 {
			top: 45%;
			left: 40%;
		}

		#body4 {
			top: 52%;
			left: 40%;
		}

		#body5 {
			top: 60%;
			left: 47%;
		}

		#body6 {
			top: 79%;
			left: 52%;
		}

		#body7 {
			top: 85%;
			left: 54%;
		}

		#body8 {
			top: 45%;
			left: 52%;
		}

		.circle5 {
			background-color: rgba(243, 64, 64, 0.59);
		}

		.circle1 {
			animation: myfirst 4s linear 0s infinite;
			background-color: #ff332996;
			-moz-animation: myfirst 4s linear 0s infinite;
			/* Firefox */
			-webkit-animation: myfirst 4s linear 0s infinite;
			/* Safari 和 Chrome */
			-o-animation: myfirst 4s linear 0s infinite;
			/* Opera */
		}

		.circle2 {
			animation: myfirst 4s linear 1s infinite;
			background-color: #ff332996;
			-moz-animation: myfirst 4s linear 1s infinite;
			/* Firefox */
			-webkit-animation: myfirst 4s linear 1s infinite;
			/* Safari 和 Chrome */
			-o-animation: myfirst 4s linear 1s infinite;
			/* Opera */
		}

		.circle3 {
			animation: myfirst 4s linear 2s infinite;
			background-color: #ff332996;
			-moz-animation: myfirst 4s linear 2s infinite;
			/* Firefox */
			-webkit-animation: myfirst 4s linear 2s infinite;
			/* Safari 和 Chrome */
			-o-animation: myfirst 4s linear 2s infinite;
			/* Opera */
		}

		.circle4 {
			animation: myfirst 4s linear 3s infinite;
			background-color: #ff332996;
			-moz-animation: myfirst 4s linear 3s infinite;
			/* Firefox */
			-webkit-animation: myfirst 4s linear 3s infinite;
			/* Safari 和 Chrome */
			-o-animation: myfirst 4s linear 3s infinite;
			/* Opera */
		}

		@keyframes myfirst {
			0% {
				-webkit-transform: scale(1);
				transform: scale(1);
				opacity: 1;
			}

			10% {
				-webkit-transform: scale(1.15);
				transform: scale(1.15);
				opacity: 0.9;
			}

			20% {
				-webkit-transform: scale(1.3);
				transform: scale(1.3);
				opacity: 0.8;
			}

			30% {
				-webkit-transform: scale(1.45);
				transform: scale(1.45);
				opacity: 0.7;
			}

			40% {
				-webkit-transform: scale(1.6);
				transform: scale(1.6);
				opacity: 0.6;
			}

			50% {
				-webkit-transform: scale(1.75);
				transform: scale(1.75);
				opacity: 0.5;
			}

			60% {
				-webkit-transform: scale(1.9);
				transform: scale(1.9);
				opacity: 0.4;
			}

			70% {
				-webkit-transform: scale(2.05);
				transform: scale(2.05);
				opacity: 0.3;
			}

			80% {
				-webkit-transform: scale(2.2);
				transform: scale(2.2);
				opacity: 0.2;
			}

			90% {
				-webkit-transform: scale(2.35);
				transform: scale(2.35);
				opacity: 0.1;
			}

			100% {
				-webkit-transform: scale(2.5);
				transform: scale(2.5);
				opacity: 0;
			}
		}

		@media screen and (max-width: 400px) {
			#body1 {
				top: 22%;
				left: 31%;
			}

			#body2 {
				top: 33%;
				left: 25%;
			}

			#body3 {
				top: 43%;
				left: 16%;
			}

			#body4 {
				top: 50%;
				left: 14%;
			}

			#body5 {
				top: 62%;
				left: 38%;
			}

			#body6 {
				top: 77%;
				left: 55%;
			}

			#body7 {
				top: 85%;
				left: 58%;
			}

			#body8 {
				top: 43%;
				left: 56%;
			}
		}
	</style>
</head>

<body>
	<div id="container"></div>
	<script type="module">
		import * as THREE from './build/three.module.js';
		import { GLTFLoader } from './jsm/loaders/GLTFLoader.js';
		import { OrbitControls } from './jsm/controls/OrbitControls.js';
		import { EffectComposer } from './jsm/postprocessing/EffectComposer.js';
		import { RenderPass } from './jsm/postprocessing/RenderPass.js';
		import { UnrealBloomPass } from './jsm/postprocessing/UnrealBloomPass.js';
		import { GUI } from './jsm/libs/dat.gui.module.js';
		import Stats from './jsm/libs/stats.module.js';


		let loader = new GLTFLoader();
		var WIDTH = window.innerWidth;
		var HEIGHT = window.innerHeight;
		var renderer, scene, camera, orbitcontrols, stats, gui, canvas;
		var clock = new THREE.Clock();
		var thismodel, mains = [];
		var boxMesh;
		var modelmaterial;
		var composer;
		var bloomPass;
		var manshow = true // 控制显示的人物是男或者女
		var showYype = 'left2right'
		var raycaster = new THREE.Raycaster();
		var mouse = new THREE.Vector2();
		var geometry
		var material
		const personTexture = new THREE.TextureLoader();
		var API = {
			strength: 1.6,
			radius: 0,
			threshold: 0.08,
			speed: 0.02,
			lineColor: 0x1D69D8
		};
		init();
		animate();
		window.addEventListener('resize', onWindowResize, false);
		function init() {
			initStats()
			initRenderer();
			initScene();
			initLights();
			initCamera();
			initRenderPass();
			init3DPerson();
			initControls();
			initHelp();
			// initGui();
		}
		//mousemove鼠标滑动事件
		function onMouseMove(event) {
			// 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
			mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
			mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
			var vector = new THREE.Vector3(mouse.x, mouse.y,0.5).unproject(camera);
			//在视点坐标系中形成射线,射线的起点向量是照相机， 射线的方向向量是照相机到点击的点，这个向量应该归一标准化。
			var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
			//射线和模型求交，选中一系列直线
			var intersects = raycaster.intersectObjects(scene.children);
			let SELECTED
			if (intersects.length > 0) {
					//选中第一个射线相交的物体
					// SELECTED = JSON.parse(intersects)[0].object;
					SELECTED = intersects[0].object;
					var intersected = intersects[0].object;
					// console.log(intersects[0].object)
			}
		}

		//点击事件
		function onMouseDblclick(event) {
			// console.log('event',event)
        //获取raycaster和所有模型相交的数组，其中的元素按照距离排序，越近的越靠前
        let intersects = getIntersects(event);
        // console.log(intersects);
        // console.log(intersects[0].object);

        //获取选中最近的Mesh对象
        //instance坐标是对象，右边是类，判断对象是不是属于这个类的
        if (intersects.length !== 0 && intersects[0].object.type === 'Mesh') {
             let selectObject = intersects[0].object;
            changeMaterial(selectObject)
        } else {
            console.log('未选中 Mesh!');
        }
    }
		 //此处设置点击事件
		 function changeMaterial(object) {
			 console.log('object',object)
			 const idx = object.position.x
			 const idy = object.position.y
			 if(idx == -20 ){
				// console.log('你点击了肩膀')				 
				alert('你点击了左肩膀')				 
			 }else if(idx == -26) {
				// console.log('你点击了手肘')
				alert('你点击了左手肘')
			}else if(idx == -36){
				// console.log('你点击了手腕')				
				alert('你点击了左手腕')				
			 }else if(idx == -40){
				// console.log('你点击了手指')
				alert('你点击了左手指')
			 }else if(idx == -10){
				alert('你点击了左膝盖')
			 }else if(idx == -13){
				alert('你点击了左足踝')
			 }else if(idx == -18){
				alert('你点击了左足趾')
			 }else if(idx == -11){
				alert('你点击了左股部')
			 }else if(idx == 20 ){
				// console.log('你点击了肩膀')				 
				alert('你点击了右肩膀')				 
			 }else if(idx == 26) {
				// console.log('你点击了手肘')
				alert('你点击了右手肘')
			}else if(idx == 36){
				// console.log('你点击了手腕')				
				alert('你点击了右手腕')				
			 }else if(idx == 40){
				// console.log('你点击了手指')
				alert('你点击了右手指')
			 }else if(idx == 10){
				alert('你点击了右膝盖')
			 }else if(idx == 13){
				alert('你点击了右足踝')
			 }else if(idx == 18){
				alert('你点击了右足趾')
			 }else if(idx == 11){
				alert('你点击了右股部')
			 }else if(idx == -0 && idy == -70){
				alert('你点击了鼻腔')
			 }else if(idx == 5){
				alert('你点击胃肠道')
			 }else if(idx == 1){
				alert('你点击血尿')
			 }else if(idx == -25){
				alert('你点击肌肉')
			 }else if(idx == 8){
				 alert('你点击皮下')
			 }
    }
		//获取与射线相交的对象数组
    function getIntersects(event) {
        event.preventDefault();// 阻止默认的点击事件执行, https://developer.mozilla.org/zh-CN/docs/Web/API/Event/preventDefault
        //console.log("event.clientX:" + event.clientX);
        //console.log("event.clientY:" + event.clientY);

        //声明 rayCaster 和 mouse 变量
        let rayCaster = new THREE.Raycaster();
        let mouse = new THREE.Vector2();

        //通过鼠标点击位置，计算出raycaster所需点的位置，以屏幕为中心点，范围-1到1
        mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
        mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; //这里为什么是-号，没有就无法点中

        //通过鼠标点击的位置(二维坐标)和当前相机的矩阵计算出射线位置
        rayCaster.setFromCamera(mouse, camera);

        //获取与射线相交的对象数组， 其中的元素按照距离排序，越近的越靠前。
        //+true，是对其后代进行查找，这个在这里必须加，因为模型是由很多部分组成的，后代非常多。
        let intersects = rayCaster.intersectObjects(scene.children, true);

        //返回选中的对象
        return intersects;
    }

		window.addEventListener('click', onMouseDblclick, false);
		window.addEventListener('mousemove', onMouseMove, false);

		function initStats() {
			stats = new Stats();
			document.body.appendChild(stats.dom);
			stats.domElement.style.position = 'absolute';
			stats.domElement.style.left = '0px';
			stats.domElement.style.top = '0px';
		}

		function initRenderer() {
			var container = document.getElementById('container');
			renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true, logarithmicDepthBuffer: true });
			renderer.setPixelRatio(window.devicePixelRatio);
			renderer.setSize(WIDTH, HEIGHT);
			renderer.toneMapping = THREE.ReinhardToneMapping; //这个不知道干嘛用
			// renderer.setClearColor(0x000000, 1)   //设置场景背景色
			container.appendChild(renderer.domElement);
		}

		function initScene() {
			scene = new THREE.Scene();
			const texture = new THREE.TextureLoader();
			const bgtexture = texture.load("./imgs/3dperson/bg5.jpeg");  //加载背景图片
			scene.background = bgtexture;			


			let material = new THREE.MeshBasicMaterial({
				color: 0xd81d1d,
			}); //材质对象Material
			
			console.log( '获得的传参', window.location.href );
			const url = window.location.href.split( '=' )[ 1 ];
			if(url){
				//console.log( 'url', url, typeof ( url ) );
				let arr = url.split( ',' );
				//console.log( 'arr', arr);
				// let arr = JSON.parse( url );
				// console.log( 'arr', arr );
				var result = [];
				for(var i=0;i<arr.length;i+=3){
						result.push(arr.slice(i,i+3));
				}
				//console.log('result',result)

				result.forEach((arr,index)=>{
					addMesh(arr,index);
				})
			}

			function addMesh(arr,index) {
				let subcutaneous = new THREE.SphereGeometry(3, 3, 3); //创建一个立方体几何对象Geometry
				let subcutaneouss = new THREE.Mesh(subcutaneous, material); //网格模型对象Mesh
				subcutaneouss.position.x = arr[0];
				subcutaneouss.position.y = arr[1];
				subcutaneouss.position.z = arr[2];
				scene.add(subcutaneouss);
			}
		}

		function initCamera() {
			camera = new THREE.PerspectiveCamera(45, WIDTH / HEIGHT, 1, 10000);
			camera.position.set(3.31, 1.65, -270); // 设置相机位置(x, y z) y控制高度,z控制当前的距离
			camera.lookAt(scene.position) // 设置相机方向(指向的场景对象)

		}

		function initControls() {
			orbitcontrols = new OrbitControls(camera, renderer.domElement);
			orbitcontrols.enableDamping = true; //惯性
			orbitcontrols.dampingFactor = 0.1; //惯性系数
			orbitcontrols.enablePan = false // 禁止左右平移
			orbitcontrols.enableZoom = false // 禁止缩放
			orbitcontrols.maxPolarAngle = Math.PI / 2 // 上下旋转的最小角度控制
			orbitcontrols.minPolarAngle = Math.PI / 2 // 上下旋转的最大角度控制
			orbitcontrols.addEventListener('change', printPosition);

		}

		function printPosition() {
			// console.info("X=" + camera.position.x);
			// console.info("Y=" + camera.position.y);
			// console.info("Z=" + camera.position.z);
		}

		function initLights() {
			// 添加点光源
			var light = new THREE.PointLight(0xe38210, 1);
			light.position.set(0, 50, 0);
			light.name = "点光源"
			scene.add(light);
			// 环境光
			var ambient = new THREE.AmbientLight(0xffffff, 0.6);
			scene.add(ambient);
		}

		function initRenderPass() {
			// 加载后期发光效果
			var renderScene = new RenderPass(scene, camera);
			//辉光
			bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 1.6, 0.1, 0.1);
			bloomPass.strength = 1.6;  // 发光强度
			bloomPass.radius = 0;  // 发光半径
			bloomPass.threshold = 0.08; // 发光阈值
			renderer.toneMappingExposure = 1.2;  //设置场景曝光度
			composer = new EffectComposer(renderer);
			composer.addPass(renderScene);
			composer.addPass(bloomPass);
		}



		function init3DPerson() {

			const modeltexture = personTexture.load("./imgs/3dperson/left2right.png"); // 加载贴图
			modeltexture.wrapS = THREE.RepeatWrapping
			modeltexture.wrapT = THREE.RepeatWrapping
			modeltexture.repeat.set(1, 1)

			modelmaterial = new THREE.MeshLambertMaterial({
				color: 0x1D69D8,
				transparent: true,//允许透明计算
				opacity: 0.9,//半透明设置
				map: modeltexture
			});

			loader.load('models/gltf/3dperson/people.glb', function (gltf) {
				thismodel = gltf.scene;
				thismodel.name = "gltfmodel";
				thismodel.scale.set(0.5, 0.5, 0.5);
				thismodel.traverse(function (child) {
					if (child.isMesh && (child.name == "男" || child.name == "女")) {
						boxMesh = child
						child.material = modelmaterial
						var edges = new THREE.EdgesGeometry(child.geometry, 0);
						var edgesMaterial = new THREE.LineBasicMaterial({
							color: 0x1D69D8,
						});
						var line = new THREE.LineSegments(edges, edgesMaterial);
						child.add(line);
					}
				});
				scene.add(thismodel);
				animate();
			}, undefined, function (e) {
				console.error(e);
			});
		}

		function initGui() {
			gui = new GUI();
			gui.add(API, 'strength', 0, 20).name("发光强度").onChange(updateUvTransform);
			gui.add(API, 'radius', 0, 20).name("发光半径").onChange(updateUvTransform);
			gui.add(API, 'threshold', 0, 1).name("发光阈值").onChange(updateUvTransform);

			gui.addColor(API, 'lineColor').name('描边颜色').onChange(function (value) {
				scene.getObjectByName("男").children[0].material.color = new THREE.Color(value)
				scene.getObjectByName("女").children[0].material.color = new THREE.Color(value)
				modelmaterial.color = new THREE.Color(value)
			});
			var dropdown = { 性别: '男' };
			var states = ['男', '女'];
			var clipCtrl = gui.add(dropdown, '性别').options(states);
			clipCtrl.onChange(function (value) {
				if (value == '男') {
					manshow = true
				} else {
					manshow = false
				}
			});

			var dropdown = { 扫描方向: '从左到右' };
			var states = ['从下到上', '从左到右'];
			var clipCtrl = gui.add(dropdown, '扫描方向').options(states);
			clipCtrl.onChange(function (value) {
				if (value == '从左到右') {
					showYype = 'left2right'
					const left2right = personTexture.load("./imgs/3dperson/left2right.png"); // 加载贴图
					// left2right.offset.set(0.5, 0.5)
					left2right.wrapS = THREE.RepeatWrapping
					left2right.wrapT = THREE.RepeatWrapping
					left2right.repeat.set(1, 1)
					modelmaterial.map = left2right

				} else {
					showYype = 'down2up'
					const down2up = personTexture.load("./imgs/3dperson/down2up.png"); // 加载贴图
					// down2up.offset.set(0.5, 0.5)
					down2up.wrapS = THREE.RepeatWrapping
					down2up.wrapT = THREE.RepeatWrapping
					down2up.repeat.set(1, 1)
					modelmaterial.map = down2up
				}
			});
			gui.add(API, 'speed', -1, 1).name("底部圆盘转速").onChange();
		}
		function updateUvTransform() {
			bloomPass.strength = API.strength;  // 发光强度
			bloomPass.radius = API.radius;  // 发光半径
			bloomPass.threshold = API.threshold; // 发光阈值
		}

		function initHelp() {
			//AxisHelper是一个坐标轴对象，添加到场景中我们就可以看到世界坐标系的具体位置
			var axes = new THREE.AxesHelper(10000);
			// scene.add(axes);
		}

		function onError() {
			alert("报错了");
		}

		function onWindowResize() {
			camera.aspect = container.offsetWidth / container.offsetHeight;
			camera.updateProjectionMatrix();
			renderer.setSize(window.innerWidth, window.innerHeight);
		}
		function animate() {
			stats.update();
			if (orbitcontrols) orbitcontrols.update();
			if (showYype == 'left2right') {
				modelmaterial.map.offset.x += 0.008;
			} else {
				modelmaterial.map.offset.y += 0.003;
			}
			if (scene.getObjectByName("底部小圆")) {
				scene.getObjectByName("底部小圆").rotation.y += API.speed
			}


			if (manshow) { //true为男子
				if (scene.getObjectByName("男")) scene.getObjectByName("男").visible = true
				if (scene.getObjectByName("女")) scene.getObjectByName("女").visible = false
			} else {
				scene.getObjectByName("女").visible = true
				scene.getObjectByName("男").visible = false
			}

			requestAnimationFrame(animate);
			renderer.clear();
			renderer.render(scene, camera);
			composer.render();
		}
	</script>
</body>

</html>